package com.b2c.handler;

import com.b2c.properties.JwtProperties;
import com.b2c.pojo.dto.AdminUserDto;
import util.AdminUserToken;
import util.ThreadLocalUtil;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.JwtException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import util.JwtUtil;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.lang.invoke.MethodHandle;

import static content.common.CommonName.ADMIN_INFO_CLAIMS_NAME;


/**
 * jwt校验拦截器
 */
@Component
@Slf4j
public class AdminJwtTokenInterceptor implements HandlerInterceptor {
    @Autowired
    JwtProperties jwtProperties;

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
        //判断当前拦截到的是Controller的方法还是其他资源
        if (handler instanceof MethodHandle) {
            return true;
        }
        //从请求头中获取token
        String token = request.getHeader(jwtProperties.getTokenName());
        //token验证，获取用户信息
        try {
            log.info("jwt验证{}", token);
            Claims claims = JwtUtil.parseJwt(jwtProperties.getAdminSecretKey(), token);
            AdminUserToken adminUserToken = claims.get(ADMIN_INFO_CLAIMS_NAME, AdminUserToken.class);
            //将用户信息放入threadLocal中
            new ThreadLocalUtil<AdminUserToken>().set(adminUserToken);
        } catch (JwtException e) {
            //验证失败响应401
            response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
            return false;
        }
        return true;
    }

    /**
     * 关闭threadlocal资源，防止内存溢出
     *
     * @param request
     * @param response
     * @param handler
     * @param modelAndView
     * @throws Exception
     */
    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView)  {
        new ThreadLocalUtil<>().remove();
    }
}
